<template>
  <div class="role-setting section-container">
    <div class="section-title">角色管理</div>
    <div class="section-actions">
      <div class="actions-left">
        <el-button-group>
          <el-button v-permission="['setting:permission:role:add']" type="primary" @click="handleAddRole">添加角色</el-button>
          <el-dropdown>
            <el-button type="primary"><i class="iconfont">&#xe78d;</i></el-button>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item v-if="hasPermission(['setting:permission:role:default'])" @click="handleSetDefaultPermission">设置默认权限</el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
        </el-button-group>
        <SearchCmp v-if="searchCmpArray.length" :searchCmpArray="searchCmpArray" :searchForm="queryData" @onSubmit="_getRoleList" />
      </div>
    </div>
    <RuifoxTable :loading="rolesTableLoading" :default-index="false" :default-checkbox="false" v-model:tableData="roleList" v-model:fieldList="fieldList">
      <!-- 多选 -->
      <template #options="{ element }">
        <div class="table-td-option">
          <el-button type="primary" link v-permission="['setting:permission:role:edit']" size="small" @click="handleEdit(element)">编辑</el-button>
          <el-button type="primary" link v-permission="['setting:permission:role:edit']" size="small" @click="handleSetPermission(element)">菜单权限</el-button>
          <el-dropdown>
            <span class="el-dropdown-link">
              <i class="iconfont">&#xe78d;</i>
            </span>
            <template #dropdown>
              <el-dropdown-menu>
                <el-dropdown-item v-if="hasPermission(['setting:permission:role:edit'])"  @click="handleSetAuthority(element)">接口权限</el-dropdown-item>
                <el-dropdown-item v-if="hasPermission(['setting:permission:role:delete'])"  @click="handleDeleteRole(element)">删除</el-dropdown-item>
              </el-dropdown-menu>
            </template>
          </el-dropdown>
        </div>
      </template>
    </RuifoxTable>
    <!-- 角色添加和编辑 -->
    <el-dialog v-model="isShowRoleMsgDialog" :title="roleWay === 1 ? '添加角色' : '编辑角色'" width="25%">
      <el-form ref="roleFormRef" :rules="roleRules" :model="roleData" label-width="100px" label-position="left" :inline-message="true">
        <el-form-item label="角色名称:" prop="title">
          <el-input v-model="roleData.title" />
        </el-form-item>
        <el-form-item label="角色别名:" prop="name">
          <el-input v-model="roleData.name" />
        </el-form-item>
        <el-form-item label="角色权限:" v-if="roleWay === 1">
          <div class="add-role-tree" v-loading="permissionMenuLoading">
            <el-tree ref="permissionTreeRole" v-if="!permissionMenuLoading" :data="permissionTreeData" :props="permissionTreeProps" show-checkbox :indent="10" node-key="id"></el-tree>
          </div>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary" :loading="optionLoading" @click="submitRoleForm(roleFormRef)">确认</el-button>
          <el-button @click="isShowRoleMsgDialog = false">取消</el-button>
        </span>
      </template>
    </el-dialog>
    <!-- 角色菜单权限设置 -->
    <el-dialog v-model="isShowPermissionDialog" :title="permissionWay === 1 ? '默认权限' : '角色权限'" width="20%">
      <div v-loading="permissionMenuLoading" style="min-height: 60px">
        <el-tree ref="permissionTree" v-if="!permissionMenuLoading" :data="permissionTreeData" :props="permissionTreeProps" show-checkbox :indent="10" node-key="id"></el-tree>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary" :loading="optionLoading" @click="submitMenuPermission">确认</el-button>
          <el-button @click="isShowPermissionDialog = false">取消</el-button>
        </span>
      </template>
    </el-dialog>
    <!-- 角色接口权限设置 -->
    <el-dialog v-model="isShowAuthorityDialog" title="接口权限" width="20%">
      <p style="margin-bottom: 10px; font-size: 12px">用于单独分配接口，分配与取消不影响角色菜单按钮所拥有的接口权限</p>
      <div v-loading="authorityLoading" style="min-height: 60px">
        <el-tree v-if="!authorityLoading" ref="authorityTree" :data="authorityTreeData" :props="authorityTreeProps" show-checkbox :indent="10" node-key="id"></el-tree>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button type="primary" :loading="optionLoading" @click="submitAuthorityPermission">确认</el-button>
          <el-button @click="isShowAuthorityDialog = false">取消</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { getRoleList, getRoleCratedBySelf, getMenuByRoleId, getMenuList, addRole, deleteRole, setRolePermission, editRole, setRoleDefaultPermission, setRoleAuthority } from '@/api/role'
import { getAuthorityTree, getAuthorityByRoleId } from '@/api/auth'
import { getUserRoutes } from '@/api/user'
import { createTreeData } from '@/utils/setting'
import { reactive, ref, nextTick } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { useStore } from 'vuex'
import { hasPermission } from '@ruifox-cms/utils'

const store = useStore()
const isShowPermissionDialog = ref(false)
const isShowRoleMsgDialog = ref(false)
const permissionTreeData = ref([])
const permissionTree = ref()
const permissionTreeRole = ref()

//获取角色列表
const searchCmpArray = ref([{ label: '角色别名', key: 'name' }])
const fieldList = ref([
  {
    title: 'ID',
    name: 'id',
    width: 60
  },
  {
    title: '角色名称',
    name: 'title'
  },
  {
    title: '角色别名',
    name: 'name'
  },
  {
    title: '操作',
    width: 300,
    fixed: 'right',
    name: 'options'
  }
])
const roleList = ref([])
const rolesTableLoading = ref(false)
const defaultQuery = {
  name: ''
}
const queryData = reactive(Object.assign({}, defaultQuery))
const _getRoleList = async () => {
  rolesTableLoading.value = true
  let res
  if (store.getters.userInfo.isSystem) {
    res = await getRoleList(queryData)
  } else {
    res = await getRoleCratedBySelf(queryData)
  }
  if (res.code === 20000) {
    roleList.value = res.data
    queryData.total = res.data.total
  }
  rolesTableLoading.value = false
}
_getRoleList()

// 所有菜单权限数据
const permissionMenuLoading = ref(false)
const permissionTreeProps = {
  children: 'children',
  label: function (data) {
    return data.title
  }
}
const getTreeData = async () => {
  let res
  if (store.getters.userInfo.isSystem) {
    res = await getMenuList({ types: '1,2,3,4' })
  } else {
    res = await getUserRoutes()
  }
  if (res.code === 20000) {
    const menus = res.data
    permissionTreeData.value = createTreeData(menus)
  }
}
getTreeData()

// 获取默认权限
const getDefaultPermission = async () => {
  permissionMenuLoading.value = true
  const res = await getMenuList({ types: '1,2,3,4', isDefault: 1 })
  nextTick(() => {
    setTimeout(function () {
      if (permissionTree.value) {
        res.data.forEach(item => {
          // 只设置叶子节点的选中状态
          if (item.hasChildren) return
          permissionTree.value.setChecked(item, true, false)
        })
      }
    }, 0)
  })
  permissionMenuLoading.value = false
}
// 设置默认权限
const permissionWay = ref(1) // 默认权限1，角色权限2
const handleSetDefaultPermission = async () => {
  isShowPermissionDialog.value = true
  permissionWay.value = 1
  getDefaultPermission()
}

// 添加角色
const roleWay = ref(1) // 添加菜单1,编辑菜单2
const optionLoading = ref(false)
const roleFormRef = ref()
const roleRules = reactive({
  title: [{ required: true, message: '请输入角色名称', trigger: 'blur' }],
  name: [{ required: true, message: '请输入角色别名', trigger: 'blur' }]
})
const defaultRoleData = {
  title: '',
  name: ''
}
const roleData = reactive(Object.assign({}, defaultRoleData))
const handleAddRole = () => {
  isShowRoleMsgDialog.value = true
  roleWay.value = 1
  getDefaultPermission()
  Object.assign(roleData, defaultRoleData)
}

// 编辑角色
const handleEdit = data => {
  isShowRoleMsgDialog.value = true
  roleWay.value = 2
  Object.assign(roleData, data)
}

// 提交角色
const submitRoleForm = async formEl => {
  if (!formEl) return
  await formEl.validate(valid => {
    if (valid) {
      optionLoading.value = true
      let _roleData = {
        title: roleData.title,
        name: roleData.name
      }
      if (roleWay.value === 1) {
        _roleData.permissionIds = permissionTreeRole.value.getCheckedNodes(false, true).map(item => {
          return item.id
        })
        addRole(_roleData).then(res => {
          if (res.code === 20000) {
            optionLoading.value = false
            isShowRoleMsgDialog.value = false
            ElMessage({
              showClose: true,
              message: '添加成功',
              type: 'success'
            })
          }
          _getRoleList()
        })
      } else {
        editRole(roleData).then(res => {
          if (res.code === 20000) {
            optionLoading.value = false
            isShowRoleMsgDialog.value = false
            ElMessage({
              showClose: true,
              message: '修改成功',
              type: 'success'
            })
            _getRoleList()
          }
        })
      }
    }
  })
}

// 删除角色
const handleDeleteRole = data => {
  ElMessageBox.confirm('是否确认删除该角色？', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    deleteRole({ id: data.id }).then(() => {
      //更新列表
      _getRoleList()
      ElMessage({
        showClose: true,
        message: '删除成功',
        type: 'success'
      })
    })
  })
}

// 菜单权限
const handleSetPermission = data => {
  isShowPermissionDialog.value = true
  permissionWay.value = 2
  getPermission(data.id)
  Object.assign(roleData, data)
}

// 获取角色菜单权限
const getPermission = async id => {
  permissionMenuLoading.value = true
  let res = await getMenuByRoleId({ id })
  nextTick(() => {
    setTimeout(function () {
      if (permissionTree.value) {
        res.data.forEach(item => {
          // 只设置叶子节点的选中状态
          if (item.hasChildren) return
          permissionTree.value.setChecked(item, true, false)
        })
      }
    }, 0)
  })
  permissionMenuLoading.value = false
}

//提交权限
const submitMenuPermission = () => {
  optionLoading.value = true
  if (permissionWay.value === 1) {
    let default_data = {
      ids: permissionTree.value.getCheckedNodes(false, true).map(item => {
        return item.id
      }),
      isDefault: true
    }
    setRoleDefaultPermission(default_data).then(() => {
      optionLoading.value = false
      isShowPermissionDialog.value = false
      ElMessage({
        showClose: true,
        message: '设置成功',
        type: 'success'
      })
    })
  } else {
    let _data = {
      id: roleData.id,
      permissionIds: permissionTree.value.getCheckedNodes(false, true).map(item => {
        return item.id
      })
    }
    setRolePermission(_data).then(() => {
      optionLoading.value = false
      isShowPermissionDialog.value = false
      ElMessage({
        showClose: true,
        message: '设置成功',
        type: 'success'
      })
    })
  }
}

// 接口权限单独分配
const isShowAuthorityDialog = ref(false)
const authorityLoading = ref(false)
const authorityTree = ref(null)
const authorityTreeData = ref([])
const authorityTreeProps = ref({
  value: 'id',
  label: 'name',
  children: 'authorityList'
})
const handleSetAuthority = async data => {
  authorityLoading.value = true
  isShowAuthorityDialog.value = true
  Object.assign(roleData, data)
  const res = await getAuthorityByRoleId({ roleId: data.id })
  if (res.code === 20000) {
    nextTick(() => {
      setTimeout(function () {
        if (authorityTree.value) {
          res.data.forEach(item => {
            // 只设置叶子节点的选中状态
            if (item.authorityList?.length > 0) return
            authorityTree.value.setChecked(item, true, false)
          })
        }
      }, 0)
    })
  }
  authorityLoading.value = false
}

// 获取全部权限树
const _getAuthorityTree = async () => {
  const res = await getAuthorityTree()
  if (res.code === 20000) {
    authorityTreeData.value = res.data
  }
}
_getAuthorityTree()

// 提交权限
const submitAuthorityPermission = async () => {
  optionLoading.value = true
  const data = {
    id: roleData.id,
    authorityIds: authorityTree.value.getCheckedNodes(false, true).map(item => {
      return item.id
    })
  }
  const res = await setRoleAuthority(data)
  optionLoading.value = false
  if (res.code === 20000) {
    ElMessage.success('设置成功')
    isShowAuthorityDialog.value = false
  }
}
</script>

<style scoped lang="scss">
.role-setting {
  .el-form {
    .el-form-item {
      margin-bottom: 10px;
    }
    .add-role-tree {
      width: 100%;
    }
  }
}
</style>
